// 延迟对象，解决promise的恰套问题，使用频率不高 ， Q库 promise库

const fs = require("fs");

// 1.延迟方法
/*
function readFile(url) {
  let dfd = Promise.deferred();
  // return new Promise((resolve, reject) => { // 产生了一个嵌套的回调
  fs.readFile(url, "utf8", function (err, data) {
    if (err) return dfd.reject(err);
    dfd.resolve(data);
  });
  return dfd.promise;
  //   });
}

readFile("./name.txt").then((data) => {
  console.log(data);
});
*/

// 2.Promise.resolve / Promise.reject  ecmascript 提供的额外方法
// 1）很多时候在使用promise的时候 我们不确定返回的内容是不是promise
// const Promise = require("./promise");
/*
let myPromise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("success");
  }, 1000);
});

// 2）用户想构建一个错误 让promise走向失败 会采用此方法
Promise.reject(myPromise).then(
  (data) => {
    console.log(data);
  },
  (err) => {
    console.log(err, "fail");
  }
);
*/

// 处理并发逻辑 Promise.race   Promise.all

// 1.Promise.race 赛跑，里面提供多个值，看谁的结果最先完成就采用谁
// 如何中断一个promise

/*
let p1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(1000);
  }, 1000);
});
let p2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject(2000);
  }, 500);
});
Promise.race([p1, p2]).then(
  (data) => {
    console.log("success", data);
  },
  (err) => {
    console.log("fail", err);
  }
);
*/

/*
let p2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("成功");
  }, 2000);
});
// 如果超过了1s 我们就让他走失败
function withAbort(promise) {
  let abort;
  let abortPromise = new Promise((resolve, reject) => {
    abort = reject;
  });
  let temp = Promise.race([promise, abortPromise]);
  temp.abort = abort;
  return temp;
}
let p3 = withAbort(p2);
// 中断方法 用户来中断
setTimeout(() => p3.abort("超时"), 2500);
p3.then(
  (data) => {
    console.log(data);
  },
  (err) => {
    console.log(err, "fail");
  }
);
*/
let p1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(500);
  }, 500);
});
let p2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(1000);
  }, 1000);
});
// 全成功才成功，有一个失败了 就走失败
// 如果想实现 先后顺序（串行）回调来实现  一起（并行）循环
// Promise.all([p2, p1, 3]).then(
//   (data) => {
//     console.log(data);
//   },
//   (err) => {
//     console.log(err, "fail");
//   }
// );
// Promise.allSettled([p1, p2]).then((data) => {
//   console.log(data);
// });

// Promise.all Promise.race Promise.allSettled(用不到)

// catch
// Promise.reject(100)
//   .then()
//   .catch(function (err) {
//     console.log(err);
//   });

// finally
/*
Promise.reject("100")
  .finally(() => {
    console.log("无论成功还是失败都执行");
    // 如果放的是promise  需要解析完这个promise之后向下执行
    return new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve("ok");
      }, 1000);
    });
  })
  .then((value) => {
    console.log("成功", value);
  })
  .catch((reason) => {
    console.log("失败", reason);
  });
*/
// catch 和 finally (都是then方法，在特定的地方可以处理逻辑)

// promisify  很多api 都是异步的 早期没有提供promise的写法

// function readFile(url) {
//   let dfd = Promise.deferred();
//   return new Promise((resolve, reject) => {
//     // 产生了一个嵌套的回调
//     fs.readFile(url, "utf8", function (err, data) {
//       if (err) return reject(err);
//       resolve(data);
//     });
//     return dfd.promise;
//   });
// }

// 高阶函数  toRef() toRefs()
function promisify(fn) {
  return (...args) => {
    return new Promise((resolve, reject) => {
      fn(...args, function (err, data) {
        // error-first
        if (err) return reject(err);
        resolve(data);
      });
    });
  };
}
function promisifyAll(o) {
  for (let key in o) {
    // 。。。
    if (typeof o[key] === "function") {
      o[key] = promisify(o[key]);
    }
  }
  return o;
}
// let readFile = promisify(fs.readFile);
const newFs = promisifyAll(fs);
newFs.readFile("./name.txt", "utf8").then((data) => {
  console.log(data);
});

// 慢慢的我们会抛弃回调， 采用promise 来简化回调 （实现链式调用、 错误处理）
